package events;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;

import org.jnetpcap.nio.JBuffer;

import packets.*;
import router.Interface;
import router.ProtocolPacketReceiver;
import router.Router;
import dataStructures.NeighborDataStructure;
import dataStructures.NeighborTable;

/**
 * Listener, der auf eingehende Hello Pakete reagiert.
 * @author pascal
 *
 */
public class ReceiveHelloListener implements ReceivePacketListener {

	

	@Override
	public void processPacket(ReceivedEvent event) throws UnknownHostException {
		
		OSPFHello receivedPacket = (OSPFHello) event.getProtocolPacket(); 
		NeighborTable table = NeighborTable.getInstance();
		Interface attachedInterface = ((ProtocolPacketReceiver)(event.getSource())).getRouterInterface();
	
			
		OSPF ospfHeader = receivedPacket.getPacket().getHeader(new OSPF());
		OSPFHello ospfHello = receivedPacket.getPacket().getHeader(new OSPFHello());
		
		InetAddress neighborsAreaID = InetAddress.getByAddress(ospfHeader.areaID());
		InetAddress neighborsID = InetAddress.getByAddress(ospfHeader.routerID());
		short neighborsNetworkMask = new Long(ospfHello.networkMask()).shortValue();
	
	
		// Falls gewisse Daten übereinstimmen
		if(neighborsAreaID.equals(attachedInterface.getInterfaceID()) && neighborsNetworkMask == attachedInterface.getNetworkMask()){
			
			NeighborDataStructure neighbor = new NeighborDataStructure(neighborsID, attachedInterface);
			// Und falls der Nachbar für dieses Interface noch nicht registriert wurde
			if(!table.getEntryForInterface(attachedInterface.getInterfaceID()).contains(neighbor)){
				
				//Nachbar zur NeighborTable hinzufügen
				table.addEntry(neighbor);
			}
						
			//InactivityTimer des Nachbarn auf jeden Fall resetten
			if(table.getNeighbor(neighborsID, attachedInterface) != null){
				ArrayList<NeighborDataStructure> neighborsToReset = table.getEntryForNeighbor(neighborsID);
				for (NeighborDataStructure neighborDataStructure : neighborsToReset) {
					neighborDataStructure.resetInactivityTimer();
				}
			}
			
			//Zustandsänderungen des Nachbarn
			NeighborDataStructure neighborInTable = table.getNeighbor(neighborsID, attachedInterface);
			
			
			ArrayList<Neighbor> neighborsOfHello = receivedPacket.getNeighbors();
			
			for (Neighbor n : neighborsOfHello) {
				//Falls eigene RouterID im Hello Paket auftaucht wird Zustand auf Init gesetzt!
				if(InetAddress.getByAddress(n.neighborID()).equals(Router.getRouter().getRouterID())){
					neighbor.changeState("IE4");
				}
				//ansonsten wird der Nachbar auf Zustand "Init" gesetzt
				else  neighbor.changeState("IE2");
			}
			
			
			
			
		}
		
		
		
		
		
	}

}
